package com.pc.tas.util;

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;

public class DBUtil {
	static Map<String, IdPair> Ids = null;
	private static PlatformTransactionManager transactionManager;
	private static DataSource ds;
	
	public synchronized static int getID(String tableName) throws Exception {
		int idForThisTime;
        if (Ids == null) {
            Ids = new HashMap<String, IdPair>();
        }
        IdPair id = (IdPair) Ids.get(tableName);
        if (id == null) {
            id = new IdPair();
            Ids.put(tableName, id);
        }

        if (id.curVal < id.maxVal) {
            idForThisTime = id.curVal++;
            return idForThisTime;
        }

        boolean isOK = false;
        Connection _conn = null;

        PreparedStatement stmt = null;
        ResultSet rs = null;       
       // PlatformTransactionManager transactionManager = (PlatformTransactionManager) SpringBeanUtil.getBean("transactionManager");
        DefaultTransactionDefinition dtf = new DefaultTransactionDefinition();
        dtf.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        TransactionStatus ts = transactionManager.getTransaction(dtf);
        try {
           // DataSource ds = (DataSource) SpringBeanUtil.getBean("datasource");
            _conn = ds.getConnection();

            stmt = _conn.prepareStatement("Lock tables tas_ids write");
            stmt.execute();
            stmt.close();

            stmt = _conn.prepareStatement(
                    "select count(*) as c from tas_ids where TableName=? ");
            stmt.setString(1, tableName);
            rs = stmt.executeQuery();
            if (rs.next()) {
                int c = rs.getInt(1);
                rs.close();
                stmt.close();
                if (c == 0) {
                    stmt = _conn.prepareStatement(
                            "Insert into tas_ids(TableName,NextValue)values(?,?)");
                    stmt.setString(1, tableName);
                    stmt.setInt(2, 50000);
                    stmt.execute();
                    stmt.close();
                }
            } else {
                rs.close();
                stmt.close();
            }



            stmt = _conn.prepareStatement(
                    "select NextValue from tas_ids where TableName=?",
                    ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
            stmt.setString(1, tableName);
            rs = stmt.executeQuery();
            rs.next();
            int ID = rs.getInt("NextValue");

            rs.close();
            stmt.close();


             stmt = _conn.prepareStatement(
                    "Update tas_ids set NextValue=NextValue+100 where TableName=?");
            stmt.setString(1, tableName);
            stmt.execute();
            stmt.close();
            
            stmt = _conn.prepareStatement("Unlock tables");
            stmt.execute();
            
            if(stmt != null) {
            	stmt.close();
            }

            isOK = true;

            id.curVal = ID;
            id.maxVal = ID + 100;
            idForThisTime = id.curVal++;
        }
        catch (Exception e) {
            e.printStackTrace();
            
            throw e;
        }
        finally{
            if(isOK){
                transactionManager.commit(ts);
            }
            else{
                transactionManager.rollback(ts);
            }
                       
            try {
            	 if(_conn!=null && _conn.isClosed()==false){
                     _conn.close();
                 }
            }catch(Exception e) {
            	e.printStackTrace();
            }
        }
        return idForThisTime;
	}

	public static void setTransactionManager(
			PlatformTransactionManager transactionManager) {
		DBUtil.transactionManager = transactionManager;
	}

	public static void setDs(DataSource ds) {
		DBUtil.ds = ds;
	}	
	
	
}

class IdPair {
    public IdPair() {
        curVal = 0;
        maxVal = 0;
    }

    public int curVal;
    public int maxVal;
}
